package ru.paswd.marketprice.storage.receipt.app.mappers;

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;
import ru.paswd.marketprice.storage.receipt.api.dto.EditableReceipt;
import ru.paswd.marketprice.storage.receipt.api.dto.Receipt;
import ru.paswd.marketprice.storage.receipt.api.dto.ReceiptItem;
import ru.paswd.marketprice.storage.receipt.api.dto.ReceiptSerialized;
import ru.paswd.marketprice.storage.receipt.app.entity.FiscalId;
import ru.paswd.marketprice.storage.receipt.app.utils.StringUtils;

import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Map;

@Mapper(componentModel = "spring")
public interface ReceiptStorageMapper {

    @Mapping(target = "id", ignore = true)
    ru.paswd.marketprice.storage.receipt.app.entity.Receipt fromDto(
            Receipt receipt);

    @Mapping(target = "id", ignore = true)
    @Mapping(target = "items", ignore = true)
    ru.paswd.marketprice.storage.receipt.app.entity.Receipt fromDto(
            EditableReceipt receipt);

    @Mapping(target = "id", ignore = true)
    @Mapping(target = "fiscalId", source = "params", qualifiedByName = "mapFiscalId")
    @Mapping(target = "dateTime", source = "params", qualifiedByName = "mapDateTime")
    @Mapping(target = "totalSum", source = "params", qualifiedByName = "mapTotalSum")
    ru.paswd.marketprice.storage.receipt.app.entity.Receipt fromDto(
            ReceiptSerialized receipt);

    @Mapping(target = "id", ignore = true)
    @Mapping(target = "receipt", ignore = true)
    ru.paswd.marketprice.storage.receipt.app.entity.ReceiptItem fromDto(
            ReceiptItem receiptItem);

    Receipt toDto(
            ru.paswd.marketprice.storage.receipt.app.entity.Receipt receipt);

    @Named("mapFiscalId")
    default FiscalId mapFiscalId(String params) {
        FiscalId fiscalId = new FiscalId();
        Map<String, String> paramsMap = StringUtils.deserializeHttpQueryMap(params);

        fiscalId.setNumber(paramsMap.get("fn"));
        fiscalId.setSign(paramsMap.get("fp"));
        fiscalId.setDocumentNumber(paramsMap.get("i"));

        return fiscalId;
    }

    @Named("mapDateTime")
    default OffsetDateTime mapDateTime(String params) {
        String dateTimeStr = StringUtils.deserializeHttpQueryMap(params).get("t");
        LocalDateTime localDateTime = parseLocalDateTime(dateTimeStr);
        return localDateTime.atOffset(ZoneOffset.ofHours(3));
    }

    @Named("mapTotalSum")
    default Integer mapTotalSum(String params) {
        String totalSumStr = StringUtils.deserializeHttpQueryMap(params).get("s");
        return Integer.valueOf(totalSumStr.replaceAll("\\.", ""));
    }

    default LocalDateTime parseLocalDateTime(String dateTime) {
        try {
            return LocalDateTime.parse(dateTime, DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmm"));
        } catch (RuntimeException ex) {
            return LocalDateTime.parse(dateTime, DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss"));
        }
    }
}
